package com.eight.cloud.message.interceptor;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.eight.cloud.core.global.model.AppUser;
import com.eight.cloud.core.global.model.LoginUser;
import com.eight.cloud.core.utils.format.ObjectFormat;
import com.eight.cloud.core.utils.quick.RSAUtils;
import com.eight.cloud.openfeign.admin.api.AppClient;
import com.eight.cloud.redisson.utils.RedisUtils;
import com.eight.cloud.redisson.utils.TokenManager;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

import static com.eight.cloud.core.global.constant.StrConstant.*;

/**
 * 握手拦截器
 *
 * @ClassName: ServletWebSocketHandshakeInterceptor
 * @Author: TXC
 * @Date: 2024-10-27 15:51
 **/
@Slf4j
@Component
public class ServletWebSocketHandshakeInterceptor implements HandshakeInterceptor {
    @Resource
    private TokenManager tokenManager;
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private AppClient appClient;

    @Override
    public boolean beforeHandshake(@NotNull ServerHttpRequest request, @NotNull ServerHttpResponse response,
                                   @NotNull WebSocketHandler wsHandler, @NotNull Map<String, Object> attributes) {
        boolean isAuth = false;
        if (request instanceof ServletServerHttpRequest) {
            String token = ((ServletServerHttpRequest) request).getServletRequest().getParameter(TOKEN);
            if (StrUtil.isNotBlank(token)) {
                isAuth = tokenAuth(token, attributes);
            } else {
                List<String> secretId = request.getHeaders().get(SECRET_ID);
                List<String> secretKey = request.getHeaders().get(SECRET_KEY);
                if (ObjectUtil.isNotNull(secretId) && ObjectUtil.isNotNull(secretKey)) {
                    isAuth = secretAuth(secretId.get(0), secretKey.get(0), attributes);
                }
            }
        }
        if (!isAuth) {
             response.setStatusCode(HttpStatus.UNAUTHORIZED);
        }
        // 继续握手返回true，否则返回false
        return isAuth;
    }

    @Override
    public void afterHandshake(@NotNull ServerHttpRequest request, @NotNull ServerHttpResponse response,
                               @NotNull WebSocketHandler wsHandler, Exception exception) {
        // 握手成功后执行
    }

    public boolean tokenAuth(String token, Map<String, Object> attributes) {
        String userId = tokenManager.getUserId(token);
        LoginUser user = ObjectFormat.objToObject(redisUtils.get(tokenManager.getUserinfoCacheKey() + userId), LoginUser.class);
        if (ObjectUtil.isNotNull(user)) {
            // 缓存中存在该用户信息，则继续握手
            attributes.put(USER_ID, userId);
            attributes.put(USER_TYPE, user.getUserType().name());
            return true;
        }
        return false;
    }

    public boolean secretAuth(String secretId, String secretKey, Map<String, Object> attributes) {
        AppUser appUser = appClient.querySecretKey(secretId);
        String decryptSecretKey = RSAUtils.decrypt(secretKey);
        if (ObjectUtil.isNotEmpty(appUser) && RSAUtils.decrypt(appUser.getSecretKey()).equals(decryptSecretKey)) {
            attributes.put(USER_ID, appUser.getUuid());
            attributes.put(USER_TYPE, appUser.getUserType().name());
            return true;
        }
        return false;
    }
}
